﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;
using MiniFox.Infrastructure;
using System.Linq.Expressions;

namespace MiniFox.Data.EntityFramework
{
    /// <summary>
    /// 
    /// </summary>
    public static class DataContextExtensions
    {
        #region 添加
        /// <summary>
        /// 添加实体到数据库
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="entities">要添加的实体,可为多个实体</param>
        public static int Insert(this DbContext dbContext, params object[] entities)
        {
            dbContext.AddRange(entities);
            int rowcount = dbContext.SaveChanges();
            return rowcount;
        }
        #endregion

        #region 修改
        /// <summary>
        /// 更新实体到数据库
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="entities">要更新的实体,可为多个实体</param>
        public static int Update(this DbContext dbContext, params object[] entities)
        {
            dbContext.UpdateRange(entities);
            int rowcount = dbContext.SaveChanges();
            return rowcount;
        }
        #endregion

        #region 删除
        /// <summary>
        /// 从数据库删除实体
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="entities">要删除的实体,可为多个实体</param>
        public static int Delete(this DbContext dbContext, params object[] entities)
        {
            dbContext.RemoveRange(entities);
            int rowcount = dbContext.SaveChanges();
            return rowcount;
        }
        
        #endregion

        /// <summary>
        /// 提交批量处理
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="batchItems">操作对象</param>
        /// <returns></returns>
        public static int CommitBatch(this DbContext dbContext, params BatchOperationItem[] batchItems)
        {
            if (batchItems == null || batchItems.Length <= 0)
                return 0;
            foreach (BatchOperationItem op in batchItems)
            {
                dbContext.Entry(op.Entity).State = op.State;
            }

            int rowcount = dbContext.SaveChanges();
            return rowcount;
        }
        #region 查询

        #region 获取查询对象
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        public static IDataQuery<TEntity> GetDataQuery<TEntity>(this DbContext dbContext) where TEntity : class
        {
            IDataQuery<TEntity> query = new EntityDataQuery<TEntity>(dbContext);
            return query;
        }
        #endregion

        #region QueryExecute~T
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static ResultSet<TEntity> QueryExecute<TEntity>(this DbContext dbContext, QueryObject request) where TEntity : class
        {
            IDataQuery<TEntity> query = dbContext.GetDataQuery<TEntity>();
            ResultSet<TEntity> result;
            if (request != null)
            {
                var lambda = request.GetQueryExpression<TEntity>();
                result = query.Execute(lambda, request.SortFields);
            }
            else
            {
                result = query.Execute(null, null);
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="queryable"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static ResultSet<TEntity> QueryExecute<TEntity>(this DbContext dbContext, IQueryable<TEntity> queryable, QueryObject request) where TEntity : class
        {
            IDataQuery<TEntity> query = dbContext.GetDataQuery<TEntity>();
            ResultSet<TEntity> result;
            if (request != null)
            {
                var lambda = request.GetQueryExpression<TEntity>();
                result = query.Execute(queryable, lambda, request.SortFields);
            }
            else
            {
                result = query.Execute(queryable, null, null);
            }
            return result;
        }
        #endregion

        #region PagedQueryExecute~T
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static PagedResultSet<TEntity> PagedQueryExecute<TEntity>(this DbContext dbContext, PagedQueryObject request) where TEntity : class
        {
            var lambda = request.GetQueryExpression<TEntity>();
            PagedResultSet<TEntity> result = dbContext.PagedQueryExecute(lambda, request.PageIndex, request.PageSize, request.SortFields);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="queryable"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static PagedResultSet<TEntity> PagedQueryExecute<TEntity>(this DbContext dbContext, IQueryable<TEntity> queryable, PagedQueryObject request) where TEntity : class
        {
            var lambda = request.GetQueryExpression<TEntity>();
            PagedResultSet<TEntity> result = dbContext.PagedQueryExecute(queryable, lambda, request.PageIndex, request.PageSize, request.SortFields);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="sortFields"></param>
        /// <returns></returns>
        public static PagedResultSet<TEntity> PagedQueryExecute<TEntity>(this DbContext dbContext, Expression<Func<TEntity, bool>> expression, int pageIndex, int pageSize, IDictionary<string, bool> sortFields) where TEntity : class
        {
            IDataQuery<TEntity> query = dbContext.GetDataQuery<TEntity>();
            PagedResultSet<TEntity> result = query.Execute(expression, sortFields, pageIndex, pageSize);
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="queryable"></param>
        /// <param name="expression"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="sortFields"></param>
        /// <returns></returns>
        public static PagedResultSet<TEntity> PagedQueryExecute<TEntity>(this DbContext dbContext, IQueryable<TEntity> queryable, Expression<Func<TEntity, bool>> expression, int pageIndex, int pageSize, IDictionary<string, bool> sortFields) where TEntity : class
        {
            IDataQuery<TEntity> query = dbContext.GetDataQuery<TEntity>();
            PagedResultSet<TEntity> result = query.Execute(queryable, expression, sortFields, pageIndex, pageSize);
            return result;
        }

        #endregion

        #endregion
    }
}
